<template>
  <div>
    <table>
      <thead>
        <tr>
          <th v-for="(th, i) in headers" :key="i" @click="go">{{ th }}</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="(row, rowIndex) in rowsList" :key="rowIndex">
          <td
            v-for="(cellValue, columnIndex) in row"
            :key="columnIndex"
            :ref="setRef(rowIndex, columnIndex)"
            :contenteditable="
              currentRow === rowIndex && currentCol === columnIndex
            "
            :class="{
              selected: isSelected(rowIndex, columnIndex),
            }"
            @blur="setCell(rowIndex, columnIndex, $event.target.textContent)"
            @keydown="handleKeydown(rowIndex, columnIndex, $event)"
            @click="focusCell(rowIndex, columnIndex, $event)"
            @dblclick="handleDoubleClick(refs[rowIndex][columnIndex])"
            @paste="handlePaste($event, refs[rowIndex][columnIndex])"
            @copy="handleCopy($event, refs[rowIndex][columnIndex])"
            @mousedown="startDrag($event)"
          >
            <div>{{ cellValue }}</div>
          </td>
        </tr>
      </tbody>
      <td>@{{ copiedData }}</td>
    </table>
  </div>
</template>

<script setup>
import { ref, reactive } from 'vue';
import { ElMessage } from 'element-plus';

const headers = ref(['Name', 'Age', 'Gender', 'Name', 'Age', 'Gender']);
const rowsList = ref([
  ['Alice', 20, 'Female', 'Alice', 20, 'Female'],
  ['Bob', 30, 'Male', 'Bob', 30, 'Male'],
]);
const isDragging = ref(false);
const copiedData = ref('');
const startDrag = (event) => {
  console.log('event: ', event);
  isDragging.value = true;

  document.addEventListener('mousemove', handleMouseMove);
  document.addEventListener('mouseup', handleMouseUp);
};
const handleMouseMove = (event) => {
  // 获取当前鼠标所在的单元格元素
  const td = event.target.closest('td');
  // console.log('td', td);
  // 判断单元格元素是否存在
  if (td) {
    // 获取当前单元格所在的列数
    const columnIndex = td.cellIndex;
    // 获取当前单元格所在的行数
    const rowIndex = td.closest('tr').rowIndex;
    // console.log('end', rowIndex, columnIndex);

    td.classList.add('highlight');
  }
};
const handleMouseUp = (event) => {
  // 获取当前鼠标所在的单元格元素
  const td = event.target.closest('td');
  // 判断单元格元素是否存在
  if (td) {
    // 获取当前单元格所在的列数
    const columnIndex = td.cellIndex;
    // 获取当前单元格所在的行数
    const rowIndex = td.closest('tr').rowIndex;
    // console.log('end', rowIndex, columnIndex);
  }
  isDragging.value = false;
  document.removeEventListener('mousemove', handleMouseMove);
  document.removeEventListener('mouseup', handleMouseUp);
};

function handleCopy($event, ref) {
  if (selectedCell.value != ref) {
    currentRow.value = null;
    let selectedValues = '';
    selectedValues = getSelectedValues();
    $event.preventDefault();
    $event.clipboardData.setData('text', selectedValues);
  }
  ElMessage({
    message: '复制成功',
    type: 'success',
  });
}

function handlePaste($event, ref) {
  if (selectedCell.value != ref) {
    const clipboardData = $event.clipboardData;
    const pastedData = clipboardData.getData('text');
    setSelectedValues(pastedData);
    $event.preventDefault();
  }
  ElMessage({
    message: '粘贴成功',
    type: 'success',
  });
}
const currentRow = ref(0);
const currentCol = ref(0);
const refs = {};
const keyFlag = ref(false);
// 获取ref
const setRef = (rowIndex, columnIndex) => {
  return (el) => {
    if (!refs[rowIndex]) {
      refs[rowIndex] = {};
    }
    refs[rowIndex][columnIndex] = el;
    // console.log('el', el);
  };
};
const selectedCell = ref(null);
// 单击事件，获取焦点并且设置index
const focusCell = (rowIndex, columnIndex, $event) => {
  console.log('$event', $event);
  // 检查当前选中的单元格是否与该单元格相同
  // console.log('selectedCell.value', selectedCell.value);
  // console.log('refs[rowIndex][columnIndex]', refs[rowIndex][columnIndex]);
  // if (selectedCell.value == refs[rowIndex][columnIndex]) {
  //   // 如果相同，则取消选择
  //   selectedCell.value = null;
  // } else {
  //   // 否则，选择该单元格并更新selectedCell变量
  //   selectedCell.value = refs[rowIndex][columnIndex];
  // }
  // console.log('selectedCell.value12', selectedCell.value);

  if ($event.shiftKey) {
    selectedRange.end = { rowIndex, columnIndex };
  } else {
    selectedRange.start = { rowIndex, columnIndex };
    selectedRange.end = { rowIndex, columnIndex };
  }
  currentRow.value = rowIndex;
  currentCol.value = columnIndex;

  // 可以键盘限制
  if (keyFlag.value) {
    keyFlag.value = false;
  }

  setTimeout(() => {
    refs[rowIndex][columnIndex].focus();
  });
};

// 双击事件，进入单个单元格的编辑
const handleDoubleClick = (ref) => {
  console.log('ref: ', ref);
  keyFlag.value = true;
  selectedRange.start = null;
  selectedRange.end = null;
  // if (selectedCell.value == ref) {
  //   // 如果相同，则取消选择
  //   selectedCell.value = null;
  // } else {
  // 否则，选择该单元格并更新selectedCell变量
  selectedCell.value = ref;
  // }
  console.log('selectedCell.value12', selectedCell.value);
};
// 失焦后,设置数据，这样的好处是减少频繁的数据更新,不然contenteditable会出现光标不准确的bug
const setCell = (rowIndex, columnIndex, value) => {
  rowsList.value[rowIndex][columnIndex] = value;
};
// 上下左右键,去设置index,并且使当前单元格聚焦
const keyDownFunc = (rowIndex, columnIndex) => {
  currentRow.value = rowIndex;
  currentCol.value = columnIndex;
  setTimeout(() => {
    refs[rowIndex][columnIndex].focus();
    console.log('refs[rowIndex][columnIndex]', refs[rowIndex][columnIndex]);
    const el = refs[rowIndex][columnIndex];
    // 此方式只针对于 input ,textarea
    // const len = refs[rowIndex][columnIndex].innerText.length

    // refs[rowIndex][columnIndex].setSelectionRange(0, len); // 设置光标到最后
    const range = document.createRange();
    range.selectNodeContents(el);
    range.collapse(false);
    const sel = window.getSelection();
    sel.removeAllRanges();
    sel.addRange(range);
  });
};
const handleKeydown = (rowIndex, columnIndex, event) => {
  const { key } = event;
  // 双击之后，锁住上下左右键的切换
  if (keyFlag.value) {
    return;
  }
  console.log('event', event);
  switch (key) {
    case 'ArrowUp':
      if (rowIndex > 0) {
        keyDownFunc(rowIndex - 1, columnIndex);
      }
      break;
    case 'ArrowDown':
      if (rowIndex < rowsList.value.length - 1) {
        keyDownFunc(rowIndex + 1, columnIndex);
      }
      break;
    case 'ArrowLeft':
      if (columnIndex > 0) {
        keyDownFunc(rowIndex, columnIndex - 1);
      }
      break;
    case 'ArrowRight':
      if (columnIndex < headers.value.length - 1) {
        keyDownFunc(rowIndex, columnIndex + 1);
      }
      break;
  }
};
const selectedRange = reactive({ start: null, end: null });
const isSelected = (rowIndex, columnIndex) => {
  const { start, end } = selectedRange;
  // console.log('start', start);
  // console.log('end', end);
  if (!start || !end) return false;
  if (
    rowIndex >= start.rowIndex &&
    rowIndex <= end.rowIndex &&
    columnIndex >= start.columnIndex &&
    columnIndex <= end.columnIndex
  ) {
    return true;
  }
  if (
    rowIndex >= end.rowIndex &&
    rowIndex <= start.rowIndex &&
    columnIndex >= end.columnIndex &&
    columnIndex <= start.columnIndex
  ) {
    return true;
  }

  return false;
};
function getSelectedValues() {
  const { rowIndex: startRow, columnIndex: startCol } = selectedRange.start;
  const { rowIndex: endRow, columnIndex: endCol } = selectedRange.end;
  let rowData = '';
  for (let i = startRow; i <= endRow; i++) {
    for (let j = startCol; j <= endCol; j++) {
      rowData += rowsList.value[i][j] + '\t';
    }
    rowData += '\n';
  }

  return rowData;
}
// const getSelectedValuesInner = () => {
//   const { rowIndex: startRow, columnIndex: startCol } = selectedRange.start;
//   const { rowIndex: endRow, columnIndex: endCol } = selectedRange.end;
//   let rowData = '';
//   for (let i = startRow; i <= endRow; i++) {
//     for (let j = startCol; j <= endCol; j++) {
//       rowData += rowsList.value[i][j] + '\t';
//     }
//     rowData += '\n';
//   }

//   return rowData;
// };
function setSelectedValues(pastedData) {
  console.log('pastedData', pastedData);
  // 如果复制数据的大小与所选单元格不匹配，则退出
  const { rowIndex: startRow, columnIndex: startCol } = selectedRange.start;
  const { rowIndex: endRow, columnIndex: endCol } = selectedRange.end;
  const rows = pastedData
    .trim()
    .split('\n')
    .map((row) => row.split('\t'));
  for (let i = 0; i < rows.length && startRow + i <= endRow; i++) {
    const row = rows[i];
    for (let j = 0; j < row.length && startCol + j <= endCol; j++) {
      // 初步 如果是选中复制，那么 拼接，其他直接替换
      rowsList.value[startRow + i][startCol + j] = row[j];
    }
  }
}

// <!-- .highlight {
//   background-color: red;
// } -->
</script>

<style>
table {
  border-collapse: collapse;
  width: 100%;
}

th,
td {
  border: 1px solid #ddd;
  padding: 8px;
  text-align: left;
}

.active {
  background-color: #ccc;
}
.selected {
  background-color: #ececec;
  position: relative;
}
</style>
